/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package se.kth.lwr.jeat.samples.generics;

import javax.measure.quantity.Dimensionless;
import javax.measure.quantity.Mass;
import javax.measure.quantity.Quantity;
import javax.measure.unit.BaseUnit;
import javax.measure.unit.SI;
import javax.measure.unit.Unit;
import org.jscience.physics.amount.Amount;
import se.kth.lwr.jeat.core.AmountDataSource;
import se.kth.lwr.jeat.core.AmountFunction;

/**
 *
 * @author davidev
 */
public class Main {

    public Main() {
        //Exempel utan JSience
        //new IntegerBox - kompilerar utan varning
        IntegerBox box = new IntegerBox(new Integer(5)); //(1)
        //new Raw box - kompilerar med varning
        Box typefreebox = new Box(new Integer(5)); //(2)
        //new boxuser kompilerar utan varning
        BoxUser user = new BoxUser(box); //(3)



        //Med JEAT
        /*
         * komilerar med varning liksom (2) ovan - jag är med på det eftersom
         * AmountDataSource är generisk av Q extends Quantity
         */
        AmountDataSource typefreesource = new AmountDataSource("name", "description", Amount.ZERO);

        /*
         * Kompilerar utan varning. Motsvarar (1) ovan. Helt i sin ordning
         */
        AmountDataSource<Dimensionless> source = new AmountDataSource<>("name", "description", Amount.ONE);
        
        
        /*
         * Kompilerar utan problem
         */
        AmountDataSource<? extends Quantity> unknownSource = new AmountDataSource<>("name", "description", Amount.ONE);

        /*
         * Kompilerar med varning Men nu? Ser inte riktigt varför inte detta
         * skulle gå men jag misstänker så klart att det har att göra med
         * typparametern på AmountDataSource
         */
        AmountFunction function1 = new AmountFunction(typefreesource);

        /**
         * Raden nedan kompilerar inte alls. Jag kan inte använda en
         * typparameter vid instansiering av AmountFunction eftersom
         * AmountFunction inte är definierad med typparameter i konstruktorn.
         * Jag har provat att göra om AmountFunction så att den tar en
         * typparameter men då uppstår ett annat fel vid kompilering av denna
         * kod. Kompileringsfelet ser ut så här:
         * C:\Users\davidev\Documents\NetBeansProjects\jeat\src\se\kth\lwr\jeat\samples\simple\Main.java:72:
         * error: no suitable constructor found for
         * AmountFunction(AmountDataSource<Dimensionless>) AmountFunction
         * function2 = new AmountFunction(source); constructor
         * AmountFunction.AmountFunction() is not applicable (actual and formal
         * argument lists differ in length) constructor
         * AmountFunction.AmountFunction(DataSource<Amount<? extends Quantity>>)
         * is not applicable (actual argument AmountDataSource<Dimensionless>
         * cannot be converted to DataSource<Amount<? extends Quantity>> by
         * method invocation conversion)
         *
         * Jag vet inte hur jag skall komma runt detta på ett bra sätt. Jag inser 
         * att det är fel att sätta den exakta typen av Quantity på den DataSource 
         * som är superobjeckt till en AmountFunction eftersom vi inte kan garantera 
         * att returvärdet är av en exakt typ. Vi vet bara att reutrvärdet är av 
         * typen ? extends Quantity. Man skulle vilja definiera AmountFunction
         * som en DataSource vars typ inte specificerades exakt vid kompilering
         * utan bara hade typen ? extends Quantity.
         * 
         * Jag har också försökt laborera mycket med klassen SourceFunction<V> för
         * att den inte skulle ärva direkt av DataSource<V>. Efter mycket arbete har
         * jag nu hittat en lösning där raderna nedan kompilerar. Den bygger på att
         * man har dubbla typparametrar till SourceFunction. En som definierar värdet
         * i funktionen (V) och en annan som definierar värdet av den DataSource som 
         * SourceFunction ärver av (T) (denna typ defineras som en subtyp till V). Hur
         * detta ser ut i praktiken kan du se under katalogen generics på länken
         * http://code.google.com/p/jeat/source/browse/#svn%2Fbranches
         * 
         * Jag tycker konstruktionen som den är i branches/generics är krånglig och
         * funderar på om APIet inte skulle må bäst av att Quantity inte användes
         * annat än i de metoder som användaren exponeras för. Om du minns så har
         * jag i tidigare exempel visat att nyttan med Quantity är oklart. Att ha
         * med det i AmountDataSource<Q extends Quantity> gör koden betyligt mer
         * komplex och svårtolkad än om man hade utelämndat det.
         */
        AmountFunction function2 = new AmountFunction(source);
        
        /*
         * Inte heller nedanstående variant vill kompilera. Felmedelande 
         * motsvarande det ovan uppträder
         */
        AmountFunction function3 = new AmountFunction(unknownSource);
        
        
    }

    public static void main(String[] args) {
    }

    /**
     * Generic version of the Box class.
     *
     * @param <T> the type of the value being boxed
     */
    public class Box<T> {
        // T stands for "Type"

        private T t;

        public Box(T t) {
            this.t = t;
        }

        public void set(T t) {
            this.t = t;
        }

        public T get() {
            return t;
        }
    }

    public class IntegerBox extends Box<Integer> {

        public IntegerBox(Integer t) {
            super(t);
        }
    }

    public class BoxUser {

        Box<Integer> box;

        public BoxUser(Box<Integer> box) {
            this.box = box;
        }
    }
}
